#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <algorithm>

const int MAX_N = 50;
const int MIN_VALUE = -1000 * MAX_N * MAX_N; // 可能的最小和

int A[MAX_N + 10][MAX_N + 10]; // 存储矩阵
int rowSum[MAX_N];   // 存储当前列区间的行和

/**
 * 
 * 时间复杂度：O(m^2 * n)
 * 空间复杂度：O(1)
 * 
 * 最大子阵
 */
int main() {
    int n, m;
    scanf("%d %d", &n, &m); // 读取矩阵大小

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            scanf("%d", &A[i][j]);
        }
    }

    int maxSum = MIN_VALUE; // 初始化最大子矩阵和

    // 枚举列区间 [left, right]
    for (int left = 0; left < m; left++) {
        // 初始化 rowSum，每次新的 left 开始时清零
        for (int i = 0; i < n; i++) {
            rowSum[i] = 0;
        }

        for (int right = left; right < m; right++) {
            // 累加当前列范围的行和
            for (int i = 0; i < n; i++) {
                rowSum[i] += A[i][right];
            }

            // 在 rowSum 上使用 Kadane 算法求最大子数组和
            int currentSum = 0, currentMax = MIN_VALUE;
            for (int i = 0; i < n; i++) {
                currentSum = std::max(rowSum[i], currentSum + rowSum[i]);
                currentMax = std::max(currentMax, currentSum);
            }

            // 更新最大子矩阵和
            maxSum = std::max(maxSum, currentMax);
        }
    }

    printf("%d\n", maxSum); // 输出最大子矩阵的和

    return 0;
}
